#include <cstdint>
#include <endian.h> // for endianness conversion
#include <cstring>

/**
 * 网络包编码类 - 大端字节序
 * 支持的类型包括：uint8_t, uint16_t, uint32_t, uint64_t, unsigned char *
 * 
 * 内部基于unsigned char数组实现, 支持动态扩容
 * 支持 append_u8, append_u16, append_u32, append_u64, append_buffer 等方法
 * 支持 data() 和 size() 方法获取编码后的数据和长度
 * 支持 reset() 方法重置编码状态
 */


class encodebuffer2 {
public:
    explicit encodebuffer2(size_t initialSize = 1024) noexcept
        : buffer_(new unsigned char[initialSize]), buffer_size_(initialSize), write_index_(0) {}

    ~encodebuffer2() {
        if (buffer_) {
            delete[] buffer_;
        }
    }

    size_t writable_bytes() const { return buffer_size_ - write_index_; }

    const unsigned char * data() const { return buffer_; }
    size_t size() const { return write_index_; }

    void reset() { write_index_ = 0; }

public:
    // 特化后的函数，方便调用
    void append_u8(uint8_t x) { append_uint(x); }
    void append_u16(uint16_t x) { append_uint(x); }
    void append_u32(uint32_t x) { append_uint(x); }
    void append_u64(uint64_t x) { append_uint(x); }

    void append_buffer(unsigned char * data, size_t len) {
        append(data, len);
    }

private:
    // 模板函数，用于将不同类型的无符号整数转换为大端字节序并追加到缓冲区
    template <typename T>
    void append_uint(T x) {
        // 将小端字节序转换为大端字节序
        T val;
        if constexpr (sizeof(T) == 1) {
            val = x; // 单字节数据无需字节序转换
        } else if constexpr (sizeof(T) == 2) {
            val = htobe16(x);
        } else if constexpr (sizeof(T) == 4) {
            val = htobe32(x);
        } else if constexpr (sizeof(T) == 8) {
            val = htobe64(x);
        }
        append((unsigned char*)&val, sizeof(val));
    }

    void append(const unsigned char * data, size_t len) {
        if (writable_bytes() < len) {
            unsigned char *ptr = new unsigned char[write_index_ + len];
            memcpy(ptr, buffer_, write_index_);
            delete[] buffer_;
            buffer_ = ptr;
        }
        memcpy(buffer_ + write_index_, data, len);
        write_index_ += len;
    }

private:
    unsigned char *buffer_;
    size_t buffer_size_;
    size_t write_index_ = 0;
};


